﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace MDSAdministration
{
    /// <summary>
    /// Interaction logic for ExportModel.xaml
    /// </summary>
    public partial class ExportModel : Window
    {
        public ExportModel()
        {
            InitializeComponent();
        }

        public CompareModel modelA { get; set; }

        public CompareModel modelB { get; set; }

        
        private void btnGenerate_Click(object sender, RoutedEventArgs e)
        {
            if (rbServerA.IsChecked.HasValue && rbServerA.IsChecked.Value)
            {
                GenerateSqlModel(modelA);
            }
            else if (rbServerB.IsChecked.HasValue && rbServerB.IsChecked.Value)
            {
                GenerateSqlModel(modelB);
            }
        }

        private void GenerateSqlModel(CompareModel model)
        {
            StringBuilder sb = new StringBuilder(); 
            if (model != null)
            {
                CreateDatabase(model, sb);
                CreateTables(model, sb);
            }
            tbSqlQuery.Text = sb.ToString();
        }

        private void CreateTables(CompareModel model, StringBuilder sb)
        {
            StringBuilder sbFK = new StringBuilder();

            foreach (var e in model.Entities)
            {
                sb.Append("-------------------------------------------------------------------------------\r\n");
                sb.Append("-- Creating Table: " + e.Value.Name + "\r\n");
                sb.Append("-------------------------------------------------------------------------------\r\n");
                sb.Append("IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[" + e.Value.Name + "]') AND type in (N'U'))\r\n");
                sb.Append("DROP TABLE [dbo].[" + e.Value.Name + "]\r\n");
                sb.Append("GO\r\n");
                sb.Append("CREATE TABLE [dbo].[" + e.Value.Name + "](\r\n");

                foreach (var a in e.Value.Attributes)
                {
                    if (a.Value.IsCode == true || a.Value.IsName == true || a.Value.IsSystem == false)
                    {
                        CreateAttribute(a, sb, sbFK);
                    }

                }
                sb.Append("CONSTRAINT [PK_" + e.Value.Name + "] PRIMARY KEY CLUSTERED\r\n");
                sb.Append("(\r\n");
                sb.Append("\t[Code] ASC\r\n");
                sb.Append(")WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]\r\n");
                sb.Append(") ON [PRIMARY]\r\n");
                sb.Append("GO\r\n");
                sb.Append("\r\n");
            }

            //We don't need to know the order of the entities
            sb.Append(sbFK.ToString());
        }

        private void CreateAttribute(KeyValuePair<string, CompareAttribute> a, StringBuilder sb, StringBuilder sbFK)
        {
            string dataType = "";
            switch (a.Value.DataTypeID)
            {   
                case Constants.DATA_TYPES_DATETIME:
                    dataType = "DATETIME";
                    break;
                case Constants.DATA_TYPES_LINK:
                    dataType = "VARBINARY(MAX)";
                    break;
                case Constants.DATA_TYPES_NUMBER:
                    {
                        int decimalScale = Convert.ToInt32(a.Value.DataTypeInformation);
                        int decimalPrecision = 38 - decimalScale;
                        
                        dataType = "DECIMAL(" + decimalPrecision + "," + decimalScale + ")" ;
                    }
                    break;
                case Constants.DATA_TYPES_TEXT:
                    {
                        if (!String.IsNullOrEmpty(a.Value.DomainEntityName) && a.Value.DomainEntityMUID != "00000000-0000-0000-0000-000000000000")
                        {
                            if (a.Value.Entity.Model.Entities.ContainsKey(CompareEntity.getEntityKey(a.Value.DomainEntityName)) == true)
                            {
                                var entity = a.Value.Entity.Model.Entities[CompareEntity.getEntityKey(a.Value.DomainEntityName)];
                                if (entity.Attributes.ContainsKey(CompareAttribute.getAttributeKey(Constants.MDSADMINISTRATION_CODE, Constants.MEMBER_TYPE_LEAF)))
                                {
                                    dataType = "NVARCHAR(" + entity.Attributes[CompareAttribute.getAttributeKey(Constants.MDSADMINISTRATION_CODE, Constants.MEMBER_TYPE_LEAF)].DataTypeInformation + ")";
                                }
                            }
                            else
                            {
                                MessageBox.Show("Can not find the following Entity: " + a.Value.DomainEntityName, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                                return;
                            }
                        }
                        else
                        {
                            dataType = "NVARCHAR(" + a.Value.DataTypeInformation + ")";
                        }
                    }
                    break;
            }

            string nullType = "NULL";
            if (a.Value.Name == Constants.MDSADMINISTRATION_CODE)
            {
                nullType = "NOT NULL";
            }

            sb.Append("\t[" + a.Value.Name + "] " + dataType + " " + nullType + ",\r\n");
            

            if (!String.IsNullOrEmpty(a.Value.DomainEntityName) && a.Value.DomainEntityMUID != "00000000-0000-0000-0000-000000000000")
            {
                sbFK.Append("ALTER TABLE [dbo].[" + a.Value.Entity.Name + "]  WITH CHECK ADD  CONSTRAINT [FK_" + a.Value.Entity.Name + "_" + a.Value.Name + "_" + a.Value.DomainEntityName + "] FOREIGN KEY([Code])\r\n");
                sbFK.Append("REFERENCES [dbo].[" + a.Value.DomainEntityName + "] ([Code])\r\n");
                sbFK.Append("GO\r\n");
                sbFK.Append("\r\n");
            }
  
        }

        private void CreateDatabase(CompareModel model, StringBuilder sb)
        {
            sb.Append("USE msdb\r\n");
            sb.Append("GO\r\n");
            sb.Append("IF EXISTS (SELECT * FROM sys.databases WHERE name = '" + model.Name + "')\r\n");
            sb.Append("BEGIN\r\n");
            sb.Append("\tDROP DATABASE [" + model.Name + "]\r\n");
            sb.Append("END\r\n");
            sb.Append("\r\n");
            sb.Append("CREATE DATABASE [" + model.Name + "]\r\n");
            sb.Append("GO\r\n");
            sb.Append("\r\n");
            sb.Append("USE " + model.Name + "\r\n");
            sb.Append("GO\r\n");
        }

        private void btnClose_Click(object sender, RoutedEventArgs e)
        {
            Close();
        }
    }
}
